﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using OpenLS.Spreadsheet.Formats.Biff.Records;

namespace OpenLS.Spreadsheet.Formats.Biff.OfficeArt
{
    class OfficeArtReadContext
    {
        private readonly BinaryReader _reader;
        private readonly Dictionary<int, ObjRecord> _objRecords;
        private readonly Dictionary<int, TxORecord> _txoRecords;
        private readonly Stack<OfficeArtRecord> _ancestors = new Stack<OfficeArtRecord>();
        public OfficeArtReadContext(BinaryReader reader, Dictionary<int, ObjRecord> objRecords, Dictionary<int, TxORecord> txoRecords)
        {
            Contract.Requires(reader != null);
            _reader = reader;
            _txoRecords = txoRecords;
            _objRecords = objRecords;
        }

        public T ReadOptionalRecord<T>(RecType type)
    where T : OfficeArtRecord, new()
        {
            Contract.Requires(this != null);
            Contract.Requires(type != 0);
            Contract.Requires(type.ToString() == typeof(T).Name);
            if (OfficeArtRecordHeader.Peek(this) != type)
                return null;
            var result = new T();
            result.Read(this);
            return result;
        }
        public ObjRecord GetObjRecord (int offset)
        {
            ObjRecord result;
            _objRecords.TryGetValue(offset, out result);
            return result;
        }
        public Stream BaseStream
        {
            get { 
                Contract.Ensures(Contract.Result<Stream>() != null);
                
                return _reader.BaseStream;
            }
        }

        public BinaryReader Reader
        {
            get
            {
                Contract.Ensures(Contract.Result<BinaryReader>() != null);
                return _reader;
            }
        }

        public Stack<OfficeArtRecord> Ancestors
        {
            get { return _ancestors; }
        }

        public byte[] ReadBytes(int count)
        {
            return _reader.ReadBytes(count);
        }

        public int ReadInt32()
        {
            return _reader.ReadInt32();
        }

        public ushort ReadUInt16()
        {
            return _reader.ReadUInt16();
        }

        public short ReadInt16()
        {
            return _reader.ReadInt16();
        }

        public byte ReadByte()
        {
            return _reader.ReadByte();
        }

        public uint ReadUInt32()
        {
            return _reader.ReadUInt32();
        }

        public OfficeArtRecord GetParent()
        {
            if (this.Ancestors.Count == 0)
                return null;
            return Ancestors.Peek();
        }

        public TxORecord GetTxoRecord(int offset)
        {
            TxORecord result;
            _txoRecords.TryGetValue(offset, out result);
            return result;
        }
    }
}